{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chap10 文件和异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "至此，我们已经掌握了组织有序而又易于使用的程序所需的基本技能，该考虑让程序的目标更加明确，用途更加强大了。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本章中，你将会学习到如何分析大量的数据；你将学会错误处理，避免程序在意外情况下直接崩溃。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "学习处理文件和报存数据，会使你的程序更易于操作。学习异常处理，可以让你更加从容地面对文件不存在，或其他导致程序崩溃的情形。在本章中，你可以提高程序的适用性，可用性和稳定性。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.1 从文件中读取数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 10.1.1读取整个文件 read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "123454651a51\n",
      "f\\s5fa64fa6f1a3f\n",
      "1a3f1a57e8131a1f\n",
      "akfjagalmbaioe;e**********end"
     ]
    }
   ],
   "source": [
    "with open('inputs.txt') as f:\n",
    "    contents = f.read()\n",
    "    print(contents, end='')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "read()方法可以读取文件的全部字符串"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "open()方法是需要提供文件的地址。要让Python打开不与程序文件位于同一个目录中的文件，需要提供文件路径 ，它让Python到系统的特定位置\n",
    "去查找"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**相对路径**是相对于该程序而言的。**绝对路径**不用考虑程序位于什么地方，是对计算机而言。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "就目前而言，最简单的做法是，要么将数据文件存储在程序文件所在的目录，要么将其存储在程序文件所在目录下的一个文件\n",
    "夹（如text_files）中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 10.1.2逐行读取文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "123454651a51\n",
      "*******f\\s5fa64fa6f1a3f\n",
      "*******1a3f1a57e8131a1f\n",
      "*******akfjagalmbaioe;e*******"
     ]
    }
   ],
   "source": [
    "with open('inputs.txt') as f:\n",
    "    for line in f:\n",
    "        print(line, end='*******')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 10.1.3 4 创建一个包含文件各行内容的列表 readlines()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['123454651a51\\n',\n",
       " 'f\\\\s5fa64fa6f1a3f\\n',\n",
       " '1a3f1a57e8131a1f\\n',\n",
       " 'akfjagalmbaioe;e']"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "with open('inputs.txt') as f:\n",
    "    lines = f.readlines()\n",
    "lines"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.2 写入文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "保存数据的最简单的方式之一是将其写入到文件中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 写入模式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = 'programming.txt'\n",
    "with open(filename, 'w') as file_object:\n",
    "    file_object.write(\"I love programming.\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "若没有附加模式，默认只读方式打开（'r'），'w'写入模式打开时，若不存在这个文件则创建一个文件写入，**若存在这个文件，就清空再写入。**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I love programming.\n"
     ]
    }
   ],
   "source": [
    "with open(filename) as f:\n",
    "    print(f.read())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 附加到文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "不会清空，继续写入。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(filename, 'a') as file_object:\n",
    "    file_object.write(\"I want to be a programmer!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I love programming.I want to be a programmer!\n"
     ]
    }
   ],
   "source": [
    "with open(filename) as f:\n",
    "    print(f.read())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.3 异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python使用被称为**异常** 的特殊对象来管理程序执行期间发生的错误。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "每当发生让Python不知所措的错误时，它都会创建一个异常对象。如果你编写了处理该异常的代码，程序将继\n",
    "续运行；如果你未对异常进行处理，程序将停止，并显示一个traceback，其中包含有关异常的报告。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 使用try expect 语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You can't divide by zero!\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    print(5/0)\n",
    "except ZeroDivisionError:\n",
    "    print(\"You can't divide by zero!\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 常见异常类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. ZeroDivisionError"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. FileNotFoundError"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sorry, this file don't exist!\n"
     ]
    }
   ],
   "source": [
    "filename = 'alice.txt'\n",
    "try:\n",
    "    with open(filename) as f_obj:\n",
    "        contents = f_obj.read()\n",
    "except FileNotFoundError:\n",
    "    print(\"Sorry, this file don't exist!\")\n",
    "else:\n",
    "    words = contents.split()\n",
    "    num_words = len(words)\n",
    "    print(\"the number is \" + str(num_words))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果你想要程序在失败时一声不吭，就可以使用pass语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = 'alice.txt'\n",
    "try:\n",
    "    with open(filename) as f_obj:\n",
    "        contents = f_obj.read()\n",
    "except FileNotFoundError:\n",
    "    pass\n",
    "else:\n",
    "    words = contents.split()\n",
    "    num_words = len(words)\n",
    "    print(\"the number is \" + str(num_words))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 决定报告那些错误"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当用户了解要分析的文件时，就应该告诉错误；若用户并不了解分析，只需要结果时就可以报告错误。向用户显示他不想看到的信息可能会降低程序的可用性。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python的错误处理结构让你能够细致地控制与用户分享错误信息的程度，要分享多少信息由你决定。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "编写得很好且经过详尽测试的代码不容易出现内部错误，如语法或逻辑错误，但只要程序依赖于外部因素，如用户输入、存在指定的文件、有网络链接，就有可能出现异常。凭借经验可判断该在程序的什么地方包含异常处理块，以及出现错误时该向用户提供多少相关的信息。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4 存储数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "很多程序都要求用户输入某种信息。不管输入的是什么，你总要将数据存储到列表或者字典中。当程序关闭时，你总是将数据保存，其中一种简单方法就是使用json模块保存数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "模块json能很简单将python数据结构转存到文件，并在下一次打开时加载该文件数据。你可以用json在Python程序之间分享数据。更重要的是，json并不是python语言的专属，其他语言也可以用json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 10.4.1 使用json.dump()和json.load()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "json.dump()用来存储数据，json.laod()用来加载数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "numbers = [1, 2, 3, 4, 6, 8, 2]\n",
    "\n",
    "filename = 'numbers.json'\n",
    "with open(filename, 'w') as f_obj:\n",
    "    json.dump(numbers, f_obj)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "dump()方法接收两个参数，一个数据，一个要存储的文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 6, 8, 2]\n"
     ]
    }
   ],
   "source": [
    "with open(filename) as f_obj:\n",
    "    numbers = json.load(f_obj)\n",
    "\n",
    "print(numbers)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "load()方法接收一个参数，存储的文件。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 10.4.2 保护和读取用户数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "What is your name? bedoom\n",
      "We'll remember you when you come back, bedoom!\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "username = input(\"What is your name? \")\n",
    "\n",
    "filename = 'username.json'\n",
    "with open(filename, 'w') as f_obj: \n",
    "    json.dump(username, f_obj) \n",
    "    print(\"We'll remember you when you come back, \" + username + \"!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Welcome back, bedoom!\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "filename = 'username.json'\n",
    "with open(filename) as f_obj: \n",
    "    username = json.load(f_obj) \n",
    "    print(\"Welcome back, \" + username + \"!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 10.4.3 重构"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将代码划分为一系列完成具体工作的函数。这样的过程被称为**重构**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "重构让代码更加清晰，更加易于理解。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Welcome back, bedoom!\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "\n",
    "\n",
    "def get_stored_username(): \n",
    "    \"\"\"如果存储了用户名，就获取它\"\"\"\n",
    "    filename = 'username.json'\n",
    "    try:\n",
    "        with open(filename) as f_obj:\n",
    "            username = json.load(f_obj)\n",
    "    except FileNotFoundError: \n",
    "        return None\n",
    "    else:\n",
    "        return username\n",
    "def greet_user():\n",
    "    \"\"\"问候用户，并指出其名字\"\"\"\n",
    "    username = get_stored_username() \n",
    "    if username:\n",
    "        print(\"Welcome back, \" + username + \"!\")\n",
    "    else:\n",
    "        username = input(\"What is your name? \")\n",
    "        filename = 'username.json'\n",
    "        with open(filename, 'w') as f_obj:\n",
    "            json.dump(username, f_obj)\n",
    "        print(\"We'll remember you when you come back, \" + username + \"!\")\n",
    "        \n",
    "greet_user()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.5 小结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本章中，你学习了：\n",
    "1. 如何使用文件\n",
    "2. 如何一次性读取整个文件，以及如何每次一行的方式读取文件的内容\n",
    "3.如何写入文件，以及如何将文本附加到文件末尾\n",
    "4. 什么是异常以以如何处理程序可能引发的异常\n",
    "5. 如何存储Python数据，避免用户每次运行程序时都需要重新提供。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
